<template>
	<view class="content">
		<image class="logo" src="/static/logo.png"></image>
		<view class="text-area">
			<text class="title">{{title}}</text>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				title: 'Hello',
				connectedDevices: [], // 存储已连接设备
				currentDeviceId: '', // 当前连接设备ID
				characteristicId: '', // 特征值ID
				writedevices: null,
				deviceId: '',
				connectedDeviceId: '',
				// 添加发送队列
				sendQueue: [],
				isSending: false,
			}
		},
		onLoad() {
			this.initBluetooth();
		},
		onUnload() {
			// 断开连接并清理监听
			this.disconnect();
			// 确保在页面卸载时清理监听器
			// 注意：uni-app没有提供移除监听的API，使用一个空函数替换回调
			try {
				// 使用空函数替换回调，这是一种变通方法
				uni.onBLECharacteristicValueChange(() => {
					// 空函数，不执行任何操作
					console.log('空回调被触发，已忽略');
				});
				console.log('已尝试清理蓝牙特征值监听');
			} catch (e) {
				console.error('清理蓝牙监听失败', e);
			}
		},
		methods: {
			reconnectDevice() {
				this.reconnect();

			},
			// 1. 初始化蓝牙适配器
			initBluetooth() {
				uni.openBluetoothAdapter({
					success: (res) => {
						console.log('蓝牙适配器初始化成功', res);
						this.startDiscovery();
					},
					fail: (err) => {
						console.error('初始化失败', err);
						if (err.errCode === 10001) {
							uni.showModal({
								title: '提示',
								content: '请开启手机蓝牙功能',
								showCancel: false
							});
						}
					}
				});
			},

			// 2. 开始搜索设备
			startDiscovery() {
				uni.startBluetoothDevicesDiscovery({
					allowDuplicatesKey: false,
					success: (res) => {
						console.log('开始搜索设备', res);
						this.listenNewDevices();
					},
					fail: (err) => {
						console.error('搜索失败', err);
					}
				});
			},

			// 监听发现新设备
			listenNewDevices() {
				let that = this;
				uni.onBluetoothDeviceFound((devices) => {
					devices.devices.forEach(device => {
						if (device.name && device.name.includes('BLE-GUC4')) {
							console.log(device);
							console.log('发现目标设备', device.deviceId);
							// this.connectedDeviceId = device.deviceId;
							// this.deviceId = device.deviceId;
							that.connectDevice(device);
						}
					});
				});
			},

			// 3. 连接设备
			connectDevice(device) {
				uni.createBLEConnection({
					deviceId: device.deviceId,
					success: (res) => {
						// 保存当前连接的设备ID
						this.deviceId = device.deviceId;
						this.currentDeviceId = device.deviceId;
						this.connectedDeviceId = device.deviceId;
						
						//设置传输单元
						uni.setBLEMTU({
							deviceId: device.deviceId,
							mtu: 32,
							success: (res) => {
								console.log('设置MTU成功', res);
							},
							fail: (err) => {
								console.log('设置MTU失败', err);
							}
						})
						console.log('连接成功', res);

						//延时1秒后执行
						setTimeout(() => {
							this.getServices(device);
						}, 10000);
					},
					fail: (err) => {
						console.error('连接失败', err);
						this.initBluetooth();
					}
				});
			},

			// 获取设备服务
			getServices(device) {
				// 先启动数据监听，确保只调用一次
				// 注意：由于uni-app没有提供移除监听的API，每次页面加载只应该调用一次listenData
				if (!this._hasSetupListener) {
					this.listenData();
					this._hasSetupListener = true;
				}
				
				uni.getBLEDeviceServices({
					deviceId: device.deviceId,
					success: (res) => {
						console.log('获取服务成功', res);
						console.log('获取服务成功', res.services);
						
						// 检查是否有服务
						if (res.services && res.services.length > 0) {
							console.log('找到服务数量:', res.services.length);
							
							// 遍历所有服务，获取特征值
							for (let i = 0; i < res.services.length; i++) {
								console.log("第" + (i + 1) + "个service:UUID:" + res.services[i].uuid);
								this.getCharacteristics(device.deviceId, res.services[i].uuid);
							}
						} else {
							console.error('未找到任何服务');
							// 尝试重新连接
							setTimeout(() => {
								this.initBluetooth();
							}, 1000);
						}
					},
					fail: (err) => {
						console.error('获取服务失败', err);
						this.initBluetooth();
					}
				});
			},

			// 获取特征值
			getCharacteristics(deviceId, serviceId) {
				this.serviceId = serviceId;
				console.log('获取特征值，设备ID:', deviceId, '服务ID:', serviceId);
				
				uni.getBLEDeviceCharacteristics({
					deviceId: deviceId, // 使用传入的deviceId，而不是this.connectedDeviceId
					serviceId: serviceId,
					success: (res) => {
						console.log('获取特征值成功', res);
						console.log('特征值数量:', res.characteristics.length);
						
						for (let i = 0; i < res.characteristics.length; i++) {
							const characteristic = res.characteristics[i];
							console.log(`特征值${i+1}:`, characteristic.uuid, '属性:', JSON.stringify(characteristic.properties));
							
							// 如果是可写特征值
							if (characteristic.properties.write) {
								if (this.writedevices == null) {
									this.writedevices = {
										"deviceId": deviceId,
										"serviceId": serviceId,
										"characteristicId": characteristic.uuid
									}
									console.log('找到可写特征值:', this.writedevices);
								}
							}
							
							// 如果是可通知特征值
							if (characteristic.properties.notify) {
								console.log('找到可通知特征值:', characteristic.uuid);
								this.notifyBLECharacteristicValueChange(
									deviceId, 
									serviceId, 
									characteristic.uuid, 
									characteristic.properties.notify
								);
							}
						}
					},
					fail: (err) => {
						console.error('获取特征值失败', err);
					}
				});
			},

			// 启用特征值变化通知
			notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicId, notify) {
				console.log('启用通知 - 设备ID:', deviceId);
				console.log('启用通知 - 服务ID:', serviceId);
				console.log('启用通知 - 特征值ID:', characteristicId);
				
				if (!notify) {
					console.log('该特征值不支持通知模式');
					return;
				}
				
				uni.notifyBLECharacteristicValueChange({
					state: true,
					deviceId: deviceId, // 使用传入的deviceId，而不是this.connectedDeviceId
					serviceId: serviceId,
					characteristicId: characteristicId,
					success: (res) => {
						console.log('启用通知成功', res);
						// 已在getServices中调用了listenData，这里不需要重复调用
						// this.listenData();
					},
					fail: (err) => {
						console.error('启用通知失败', err);
					}
				});
			},

			// 4. 监听接收数据
			listenData() {
				let that = this;
				// 注意：uni-app没有提供移除监听的API，可能会导致多次监听
				// 这里直接注册监听，每次连接设备时只调用一次此方法
				console.log('开始监听特征值变化');
				
				// 存储回调函数，以便在断开连接时可以替换为空函数
				if (!this._bleValueChangeCallback) {
					this._bleValueChangeCallback = (res) => {
						const value = res.value;
						console.log('收到数据特征值:', res.characteristicId);
						console.log('收到数据服务:', res.serviceId);
						console.log('收到数据设备:', res.deviceId);
						console.log('收到数据十六进制:', that.ab2hex(res.value));
						console.log('收到数据:', value);
						
						if (value && value.byteLength > 0) {
							console.log('起始码:', value[0]);
							console.log('结束码:', value[value.length - 1]);
							console.log('包类型:', value[1]);
							// 解析数据逻辑...
							that.checkResultData(that.ab2hex(res.value), res.deviceId);
						} else {
							console.error('收到空数据');
						}
					};
				}
				
				// 注册监听
				uni.onBLECharacteristicValueChange(this._bleValueChangeCallback);
				console.log('已启动特征值变化监听');
			},


			checkResultData(value, deviceId) {
				let that = this;
				console.log('value=', value);
				let len = value.length;
				if (len < 255) {
					let frist = value[0];
					if (frist != 42) {
						console.log('起始码错误');
						return false;
					}
					let endData = value[len - 1];
					if (endData != 35) {
						console.log('结束码错误');
						return false;
					}
					let packType = value[1];
					if (packType == 1) { //发送时间

						let now = new Date();
						let yy = now.getFullYear();
						let mm = now.getMonth() + 1;
						let dd = now.getDate();
						let hh = now.getHours();
						let mi = now.getMinutes();
						let ss = now.getSeconds();
						console.log('发送时间 , 不处理', parseInt(yy % 256));
						const buffer = new ArrayBuffer(13)
						const dataView = new DataView(buffer)
						dataView.setUint8(0, 0x2a)
						dataView.setUint8(1, 1)
						dataView.setUint8(2, 8)
						dataView.setUint8(3, 0)
						dataView.setUint8(4, parseInt(yy / 256))
						dataView.setUint8(5, parseInt(yy % 256))
						dataView.setUint8(6, parseInt(mm))
						dataView.setUint8(7, parseInt(dd))
						dataView.setUint8(8, parseInt(hh))
						dataView.setUint8(9, parseInt(mi))
						dataView.setUint8(10, parseInt(ss))
						dataView.setUint8(11, that.bccCheck(dataView))
						dataView.setUint8(12, 0x23)

						console.log('buffer', buffer);
						console.log('dataView', dataView);
						console.log(that.writedevices);

						this.writeBLECharacteristicValue(buffer, that.writedevices.deviceId, that.writedevices.serviceId,
							that.writedevices.characteristicId, packType)

						return false;
					}


					if (packType == 4) {
						console.log('倒计时 , 不处理');
						return false;
					}
					if (packType == 2) {
						console.log('设备信息帧 , 不处理');
						const buffer = new ArrayBuffer(6)
						const dataView = new DataView(buffer)
						dataView.setUint8(0, 0x2a)
						dataView.setUint8(1, 2)
						dataView.setUint8(2, 1)
						dataView.setUint8(3, 0) //成功
						dataView.setUint8(4, that.bccCheck(dataView))
						dataView.setUint8(5, 0x23)


						this.writeBLECharacteristicValue(buffer, that.writedevices.deviceId, that.writedevices.serviceId,
							that.writedevices.characteristicId, packType)
						return false;
					}
					if (packType == 3) {
						console.log('正式尿酸数据');
						console.log('value=', value);

						var d = new Uint8Array(value.slice(12, 16));
						console.log(d.buffer);
						var dataView = new DataView(d.buffer);
						var blobLen = dataView.getInt32(0);

						console.log("测量尿酸值：" + blobLen);

						const buffer1 = new ArrayBuffer(7)
						const dataView1 = new DataView(buffer1)
						dataView1.setUint8(0, 0x2a)
						dataView1.setUint8(1, 3)
						dataView1.setUint8(2, 2)
						dataView1.setUint8(3, 0) //成功
						dataView1.setUint8(4, 0)
						dataView1.setUint8(5, that.bccCheck(dataView))
						dataView1.setUint8(6, 0x23)


						this.writeBLECharacteristicValue(buffer1, that.writedevices.deviceId, that.writedevices.serviceId,
							that.writedevices.characteristicId)

						let niansuanHistoryTime = "" + value[6] + value[7] + value[8] + value[9] + value[10]

						let niansuanHistoryTimeStorage = uni.getStorageSync('niansuanHistoryTime')
						if (niansuanHistoryTime != niansuanHistoryTimeStorage) {
							uni.setStorageSync('niansuanHistoryTime', niansuanHistoryTime)
						}
					}
					console.log('return true');
					return true;
				}
				return false;
			},

			writeBLECharacteristicValue(buffer, deviceId, serviceId, characteristicId, packType) {
				let that = this;
				console.log(new Uint8Array(buffer));
				console.log("发送数据" + buffer + '111' + deviceId + "111" + serviceId + "111" + characteristicId)
				setTimeout(() => {
					uni.writeBLECharacteristicValue({
						deviceId,
						serviceId,
						characteristicId,
						value: buffer,
						success: function(res) {
							console.log('发包成功')
							console.log(res)
						},
						fail: function(res) {
							console.log(res)
							console.log('发包失败')
							if (res.errCode === 10007) {
								console.log('尝试重新写入...');
								that.writeBLECharacteristicValue(buffer, deviceId, serviceId,
									characteristicId, packType); // 自动重试
							}
						},
						complete: function(res) {
							console.log('完成')

							console.log(res)
							// if(packType == 2){
							// 	that.writeBLECharacteristicValue(buffer, deviceId, serviceId,
							// 		characteristicId,packType); // 自动重试
							// }
						}
					})
				}, 50)

			},
			ab2hex(buffer) {
				console.log(new Uint8Array(buffer));
				const hexArr = Array.prototype.map.call(
					new Uint8Array(buffer),
					function(bit) {

						// return ('00' + bit.toString(16)).slice(-2)
						return parseInt(bit.toString(10));
					}
				)
				console.log(hexArr);
				return hexArr;
			},

			//数据验证
			bccCheck(dataView) {
				let checksum = 0x00
				for (let i = 1; i < dataView.byteLength - 2; i++) {
					checksum ^= dataView.getInt8(i)
				}

				return checksum
			},



			// 5. 断开连接
			disconnect() {
				if (!this.currentDeviceId) return;

				// 如果存在回调函数，将其替换为空函数以避免重复监听
				if (this._bleValueChangeCallback) {
					// 使用空函数替换回调
					uni.onBLECharacteristicValueChange(() => {
						console.log('空回调被触发，已忽略');
					});
					console.log('已替换蓝牙特征值监听为空函数');
				}

				uni.closeBLEConnection({
					deviceId: this.currentDeviceId,
					success: (res) => {
						console.log('断开连接成功', res);
						// 重置监听器状态标志，以便下次连接时能重新设置监听
						this._hasSetupListener = false;
						this.stopDiscovery();
					}
				});
			},

			// 停止搜索
			stopDiscovery() {
				uni.stopBluetoothDevicesDiscovery({
					success: (res) => {
						console.log('停止搜索成功', res);
					}
				});
			},

			// 6. 重新连接设备
			reconnect() {
				if (!this.currentDeviceId) return;

				this.connectDevice(this.currentDeviceId);
			},

		}
	}
</script>

<style>
	.content {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}

	.logo {
		height: 200rpx;
		width: 200rpx;
		margin-top: 200rpx;
		margin-left: auto;
		margin-right: auto;
		margin-bottom: 50rpx;
	}

	.text-area {
		display: flex;
		justify-content: center;
	}

	.title {
		font-size: 36rpx;
		color: #8f8f94;
	}
</style>